// Various filetype supports
const supportsFLV  = !!document.createElement("video").canPlayType("video/x-flv");
const supportsAVI  = !!document.createElement("video").canPlayType("video/avi");
const supportsWMV  = !!document.createElement("video").canPlayType("video/x-ms-wmv");
const supportsWAV  = !!document.createElement("audio").canPlayType("audio/wav");
const supportsWebM = !!document.createElement("video").canPlayType("video/webm") && false;
var downloadLink = document.createElement("a");

function getFormatForRect(arg1,arg2)
{
	var list = arg1.concat();
	var loc2,loc3,loc4,loc5,loc6,loc7,loc8,loc9,loc10,loc11;

	loc3 = arg2.width;
	loc4 = arg2.height;
	loc5 = 16 / 9;
	if (loc3 > Math.round(loc5 * loc4))
	{
		loc3 = Math.round(loc5 * loc4);
	}
	loc6 = loc3 * loc4;
	for (loc10 = 0; loc10 < list.length; loc10++)
	{
		loc7 = list[loc10];
		loc8 = loc7.type.size.width * loc7.type.size.height;
		loc9 = (loc7.type.name != "360p") ? 0.85 : 0.26;
		if (loc8 * loc9 < loc6 && loc7.type.type != "FLV")
		{
			return loc7;
		}
		loc2 = loc7;
	}
	return loc2;
}

function isSubdomain(arg1,arg2){
	return (new Regexp("^https?:\\/\\/([a-z0-9\\-]{1,63}\\.)*(" + arg2.join("|").replace(new RegExp("\\.", "g"), "\\.") + ")(:[0-9]+)?([\\/\\?\\#]|$)", "i")).test(arg1);
}

function isTrustedDomain(arg){
	var loc = ["youtube.com", "ytimg.com", "googlevideo.com", "google-liveplayer.appspot.com", "vp.video.l.google.com", "c.googlesyndication.com", "google.org", "docs.google.com", "video.google.com", "corp.google.com"];
	return isSubdomain(arg,loc);
}

function downloadURL(url) {
	if(window.top != window){
		return;
	}
    downloadLink.href = url;
    
    var event = document.createEvent("MouseEvents");
    event.initMouseEvent("click", true, true, window, 1, 0, 0, 0, 0, false, true, false, false, 0, null);
    
    downloadLink.dispatchEvent(event);
}

if(!Element.prototype.click){
	Element.prototype.click = function(){
		var event = document.createEvent("MouseEvents");
		event.initMouseEvent("click",true,true,window,1,0,0,0,0,false,false,false,false,0,null);
		this.dispatchEvent(event);
	}
}

String.prototype.contains = function(str){
	return this.indexOf(str) != -1
}

function viewInQuickTimePlayer(mediaURL){
	if(window.top != window){
		return;
	}
    var QTObject = document.createElement("embed");
    QTObject.allowedToLoad = true;
    QTObject.className = "CTFQTObject";
    QTObject.setAttribute("type", "video/quicktime");
    QTObject.setAttribute("width", "0");
    QTObject.setAttribute("height", "0");
    // need an external URL for source, since QT plugin doesn't accept safari-extension:// protocol
    // Apple has a small 1px image for this exact purpose
    QTObject.setAttribute("src", "http://images.apple.com/apple-events/includes/qtbutton.mov");
    QTObject.setAttribute("href", mediaURL);
    QTObject.setAttribute("target", "quicktimeplayer");
    QTObject.setAttribute("autohref", "true");
    QTObject.setAttribute("controller", "false");
    document.body.appendChild(QTObject);
    setTimeout(function() {document.body.removeChild(QTObject);}, 1000);
};

function roundToArray(n, a) { return a.reduce(function (y, z) { return ((Math.abs(n - y) > Math.abs(n - z)) ? z : y) }); }

Element.prototype.__defineGetter__("computedStyle",function(){
	return document.defaultView.getComputedStyle(this, null);
});

Element.prototype.__defineGetter__("pageLeft",function(){
	var obj = this;
	var curleft = 0;
	do{
		curleft += obj.offsetLeft;
	}while(obj = obj.offsetParent);
	return curleft;
});
Element.prototype.__defineGetter__("pageTop",function(){
	var obj = this;
	var curtop = 0;
	do{
		curtop += obj.offsetTop;
	}while(obj = obj.offsetParent);
	return curtop;
});

String.prototype.parseInt = function(radix){
	return parseInt(this,radix);
}

injectScript = function(script){
	var scriptTag = document.createElement("script");
	scriptTag.type = "text/javascript";
	scriptTag.textContent = script;
	document.head.appendChild(scriptTag);
}

//create function, it expects 2 values.
Element.prototype.insertAfter = function(newElement,targetElement) {
	//if the parent's lastchild is the targetElement...
	if(this.lastChild == targetElement) {
		//add the newElement after the target element.
		this.appendChild(newElement);
	} else {
		// else the target has siblings, insert the new element between the target and it's next sibling.
		this.insertBefore(newElement, targetElement.nextSibling);
	}
}

Element.prototype.isAncestor = function(tag){
	o = this;
	for(true;o = o.parentNode;true)
		if(o == tag)
			return o;
	return null;
}

String.prototype.between = function(prefix, suffix) {
	s = this;
	var i = s.indexOf(prefix);
	if (i >= 0) {
		s = s.substring(i + prefix.length);
 	}
	if (suffix) {
		i = s.indexOf(suffix);
		if (i >= 0) {
	  		s = s.substring(0, i);
		}
	}
	return s.toString();
}

function zeroPad(num,count){
	var numZeropad = num + '';
	while(numZeropad.length < count) {
		numZeropad = "0" + numZeropad;
	}
	return numZeropad;
}

function getQueryString(queryString) {
	var assoc = {};
	var keyValues = queryString.split('&');
	for (var i = 0; i < keyValues.length; i++) {
		var split = keyValues[i].split('=');
		var key = split.shift();
		var value = split.join("=");
		if(!value){
			value = true;
		}else if(value.toLowerCase() == "true"){
			value = true;
		}else if(value.toLowerCase() == "false"){
			value = false;
		}else{
			value = unescape(value).replace(/\+/g," ");
		}
		assoc[key] = value;
	}
	return assoc;
}

Element.prototype.getParamByName = function(name){
	params = this.getElementsByTagName("param");
	for(var i = 0; i < params.length; i++){
		if(params[i].getAttribute("name").toLowerCase() == name.toLowerCase()){
			return params[i];
		}
	}
	param = document.createElement("param");
	param.name = name;
	param.value = ""
	return param;
}

Element.prototype.getEmbed = function(){
	if(this.getElementsByTagName("embed").length > 0){
		return this.getElementsByTagName("embed")[0];
	}else{
		return false;
	}
}

videos = new Object();

//This function was actually copied and pasted with few modifications from the original Flash MP3 Plaer's Application.as source file, viewable at http://tools.assembla.com/1pixelout/browser/audio-player/trunk/source/classes/Application.as
function decodeFlashMP3(sourceStr)
	{
		var ntexto = "";
		var nntexto = "";
		var codeKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
		var charCode, charChar, charCodeBin, i;
		for(var i=0; i<sourceStr.length; i++)
		{
			charCode = codeKey.indexOf(sourceStr.substr(i,1)); // char index
			charCodeBin = ("000000" + charCode.toString(2)).substr(-6,6); // char index in binary, 6 bits
			ntexto += charCodeBin;
		}
		for (i=0; i< ntexto.length; i = i +8) {
			charCodeBin = ntexto.substr(i, 8); // char code in binary
			charCode = parseInt(charCodeBin, 2);
			charChar = String.fromCharCode(charCode);
			nntexto += charChar;
		}
		return (nntexto);
	}

function collectionToArray(collection)
{
	var ary = [];
	for(var i=0, len = collection.length; i < len; i++)
	{
		ary.push(collection[i]);
	}
	return ary;
}

function zeroPad(num,count)
{
var numZeropad = num + '';
while(numZeropad.length < count) {
numZeropad = "0" + numZeropad;
}
return numZeropad;
}

function handleMessage(event) {
	// This is a Safari Extension message
	if (event.name == "injectVideo") {
		injectVideo(event.message);
		return;
	}
	if (event.name == "injectHTML5Video") {
		injectHTML5Video(event.message);
		return;
	}
	if (event.name == "buildServicePlayer"){
		buildServicePlayer(event.message.videoId,event.message.playerId,false);
		return;
	}
	if (event.name == "restoreVideo"){
		restoreVideo(event.message);
		return;
	}
	if (event.name == "downloadURL"){
		downloadURL(event.message);
		return;
	}
	if (event.name == "viewQT"){
		viewInQuickTimePlayer(event.message);
		return;
	}
	if (event.name == "loadNewVideo"){
		loadNewVideo(event.message);
		return;
	}
}
function handleWindowMessage(event){
	try{
		var message = JSON.parse(event.data);
	}catch(e){
		return; // It's not mine!
	}
	if(message.action == "callMethodOfElement"){
		document.getElementById(message.target)[message.fn].apply(document.getElementById(message.target),message.args);
	}else if(message.action == "callMethodOfObject"){
		window[message.target][message.fn].apply(window[message.target],message.args)
	}else if(message.action == "callFunction"){
		window[message.fn].apply(window,message.args);
	}else if(message.action == "callFunctionWithElement"){
		window[message.fn].apply(document.getElementById(message.target),message.args);
	}
}

window.addEventListener("message",handleWindowMessage, false);

safari.self.addEventListener("message", handleMessage, false);

function fullScreenChange(event){
	if(event.target.classList.contains("video-full-window") && !document.webkitIsFullScreen){
		fullButtonClicked(event.target,true);
	}
}

function toggleAnnotations(event){
	this.firstChild.classList.toggle("enabled");
	this.parentNode.parentNode.parentNode.getElementsByTagName("canvas")[0].classList.toggle("hidden");
}

function injectVideo(video) {
	var player = document.getElementById(video.playerId);
	if (player == null) {
		return;
	}
	
	player.videoData = video;
	
	injectScript("document.getElementById('"+player.id+"').videoData = "+JSON.stringify(video)+";");
	
	if(player.hasChildNodes()){
		return;
	}

	var videoEl = document.createElement('video');

	videoEl.id = player.id+"-player";
	videoEl.style.width = "100%";
	videoEl.style.height = "100%";
	videoEl.style.position = "absolute";
	videoEl.controls = false;
	videoEl.player = player;
	videoEl.className = "html5-video-player-tag";
	videoEl.siteName = video.service;
	if(video.siteURL){
		videoEl.siteURL = video.siteURL;
	}
	
	if (player.className.indexOf('html5-video-autoplay') !== -1 || video.autoplay === true || video.autoplay === "true") {
		videoEl.autoplay = true;
	}else{
		videoEl.preload = "none";
	}
	
	player.style.position = "relative";
	videoEl.style.setProperty("postition","absolute");
	videoEl.style.top = "0px";
	videoEl.style.left = "0px";
	
	videoEl.style.setProperty("z-index","1");
	var contentDiv = document.createElement("div");
	contentDiv.className = "video-player-content full";
	
	videoEl.addEventListener("loadedmetadata",jumpToTime,false);	
	contentDiv.appendChild(videoEl);
	
	// On exit from full-screen, return to normal size (not full window).
	document.addEventListener("webkitfullscreenchange",fullScreenChange,false);
	
	if(video.hasAnnotations){
		videoEl.hasAnnotations = true;
		addAnnotationsEl(videoEl);
		videoEl.annotations = video.annotations;
		videoEl.addEventListener("timeupdate",updateAnnotations,false);
	}

	player.appendChild(contentDiv);

	if(typeof video.src == "string"){
		videoEl.src = video.src;
	}else if(typeof video.src == "object"){
		videoEl.currentQuality = getFormatForRect(video.src,{width: parseInt(videoEl.computedStyle.width), height: parseInt(videoEl.computedStyle.height)});
		videoEl.src = videoEl.currentQuality.url;
		videoEl.srcList = video.src;
	}
	
	if(videoEl.src.indexOf("youtube") != -1) {
		var cdn = Math.ceil(Math.random()*4);
		videoEl.poster = "http://i" + cdn + ".ytimg.com/vi/" + video.id + "/hqdefault.jpg";
	} else if(video.posterFrame){
		videoEl.poster = video.posterFrame;
	}
	
	var controlsElement = buildControlsElement(player,videoEl);
	
	player.appendChild(controlsElement);
	
	if(parseInt(player.computedStyle.height) <= 8){
		player.style.height = parseInt(player.computedStyle.width)*(9/16)+"px";
	}
	
	videoEl.isPlaying = false;
	
	player.videoEl = videoEl;
	
	injectScript("document.getElementById('"+player.id+"').videoEl = document.getElementById('"+videoEl.id+"');");
	
	contentDiv.style.setProperty("-webkit-transform","scaleY("+(1-(38/parseFloat(player.computedStyle.height)))+") translateY(-21px)");
	
	var seekJS = "if(window.yt && window.yt.www && window.yt.www.watch && window.yt.www.watch.player && window.yt.www.watch.player.seekTo){window.yt.www.watch.player.seekTo = function(t){var player = document.getElementsByTagName('video')[0]; if(player.readyState != 4){player.jumpTime = t;player.preload='auto';player.autoplay = true;player.load();}else{player.currentTime = t; player.play();} };}";
	injectScript(seekJS);
	
	videoEl.state = -1;
	
	player.apiConnector = buildYTApiConnector(video,player,player.previousSibling);
	
	videoEl.apiConnector = player.apiConnector;
	injectScript("if(window.onYouTubePlayerReady){onYouTubePlayerReady(\""+video.flashVars.playerapiid+"\");}");
	if(video.flashVars.jsapicallback){
		injectScript("if(window."+video.flashVars.jsapicallback+"){"+video.flashVars.jsapicallback+"(\""+video.flashVars.playerapiid+"\");}");
	}
	player.apiConnector.setPlayerState(-1);
	player.apiConnector.fireEvent("onReady",video.flashVars.playerapiid);
}

function loadNewVideo(video){
	var player = document.getElementById(video.playerId);
	if (player == null) {
		return;
	}
	
	player.videoData = video;
	
	var videoEl = player.videoEl;
	
	injectScript("document.getElementById('"+player.id+"').videoData = "+JSON.stringify(video)+";");
	
	if(video.hasAnnotations){
		videoEl.hasAnnotations = true;
		resetAnnotations(videoEl);
		videoEl.annotations = video.annotations;
		videoEl.addEventListener("timeupdate",updateAnnotations,false);
	}else{
		videoEl.hasAnnotations = false;
		videoEl.removeEventListener("timeupdate",updateAnnotations,false);
	}
	
	if(typeof video.src == "string"){
		videoEl.src = video.src;
	}else if(typeof video.src == "object"){
		videoEl.currentQuality = getFormatForRect(video.src,{width: parseInt(videoEl.computedStyle.width), height: parseInt(videoEl.computedStyle.height)});
		videoEl.src = videoEl.currentQuality.url;
		videoEl.srcList = video.src;
	}
	
	if(videoEl.src.indexOf("youtube") != -1) {
		var cdn = Math.ceil(Math.random()*4);
		videoEl.poster = "http://i" + cdn + ".ytimg.com/vi/" + video.id + "/hqdefault.jpg";
	} else if(video.posterFrame){
		videoEl.poster = video.posterFrame;
	}
	
	var list = player.getElementsByClassName("video-quality-list")[0];
	
	if(videoEl.srcList && !list){
		var qualityDiv = document.createElement("div");
		qualityDiv.className = "video-quality-div";
		
		var qualityButton = document.createElement("span");
		qualityButton.className = "video-quality-button";
		qualityButton.innerHTML = videoEl.currentQuality.type.name;
		qualityButton.addEventListener("click",toggleQualityMenu,false);
		qualityDiv.appendChild(qualityButton);
		
		var qualityList = document.createElement("ul");
		qualityList.className = "video-quality-list";
		
		qualityDiv.appendChild(qualityList);
		
		controlsElement.appendChild(qualityDiv);
	}else if(!videoEl.srcList){
		list.parentNode.parentNode.removeChild(list.parentNode);
	}
	
	if(videoEl.srcList){
		while(list.hasChildren()){
			list.removeChild(list.firstChild);
		}
		for(var l = 0; l < videoEl.srcList.length; l++){
			var fmt = videoEl.srcList[l];
			var fmtLi = document.createElement("li");
			fmtLi.className = "video-format-item video-format-"+fmt.type.type+" video-format-HD-"+fmt.type.HD;
			fmtLi.innerHTML = fmt.type.name;
			fmtLi.fmt = fmt;
			fmtLi.addEventListener("click",switchQuality,false);
			list.appendChild(fmtLi);
		}
	}
	
	videoEl.isPlaying = false;
	
	injectScript("document.getElementById('"+player.id+"').videoEl = document.getElementById('"+videoEl.id+"');");
	
	videoEl.state = -1;
}

function buildYTApiConnector(video,player,connector){
	if(!connector.id){
		connector.id = video.id + "-Connector";
	}
	connector.player = player;
	connector.className = "YouTube-API-Connector no-load-video";
	injectScript("document.getElementById('"+connector.id+"').player = document.getElementById('"+player.id+"')");
	connector.playVideo = function(){
		this.player.videoEl.play();
	}
	connector.pauseVideo = function(){
		this.player.videoEl.pause();
	}
	connector.stopVideo = function(){
		this.player.videoEl.pause();
		this.player.videoEl.src = "";
	}
	connector.seekTo = function(seconds,allowSeekAhead){
		if((!allowSeekAhead && this.player.videoEl.seekable.end(this.player.videoEl.seekable.length-1) < seconds) || allowSeekAhead){
			try{
				this.player.videoEl.currentTime = seconds;
			}catch(e){
				// gulp();
			}
		}
	}
	connector.clearVideo = function(){
		this.player.videoEl.src = "";
	}
	connector.mute = function(){
		this.player.videoEl.muted = true;
	}
	connector.unMute = function(){
		this.player.videoEl.muted = false;
	}
	connector.isMuted = function(){
		return this.player.videoEl.muted;
	}
	connector.setVolume = function(volume){
		this.player.videoEl.volume = volume/100;
	}
	connector.getVolume = function(){
		return this.player.videoEl.volume*100;
	}
	connector.setSize = function(width,height){
		//FIXME: I really don't feel like writing a function for this right now.
	}
	connector.getPlayerState = function(){
		return this.player.videoEl.state;
	}
	connector.setPlayerState = function(state){
		this.player.videoEl.state = state;
		injectScript("if(document.getElementById('"+this.player.videoEl.id+"')){document.getElementById('"+this.player.videoEl.id+"').state = "+state+";}");
		this.fireEvent("onStateChange",state);
	}
	connector.getCurrentTime = function(){
		return this.player.videoEl.currentTime;
	}
	connector.getPlaybackQuality = function(){
		//FIXME: Write this function
	}
	connector.setPlaybackQuality = function(quality){
		//FIXME: Write this function
	}
	connector.getAvailableQualityLevels = function(){
		//FIXME: Write this function
	}
	connector.getDuration = function(){
		if(this.player.videoEl.duration){
			return this.player.videoEl.duration;
		}else{
			return this.player.videoEl.videoData.duration;
		}
	}
	connector.getVideoUrl = function(){
		return "http://www.youtube.com/watch?v="+this.player.videoData.id;
	}
	connector.getVideoEmbedCode = function(){
		return "<object style='height: 390px; width: 640px'>" + "<param name='movie' value='http://www.youtube.com/watch?v="+this.player.videoData.id+"'>" + "<param name='allowFullScreen' value='true'>" + "<param name='allowScriptAccess' value='always'>" + "<embed src='http://www.youtube.com/watch?v="+this.player.videoData.id+"' type='application/x-shockwave-flash'" + " allowfullscreen='true' allowScriptAccess='always'" + " width='640' height='390'>" + "</object>";
	};
	connector.cueRanges = {};
	connector.addCueRange = function(name,start,end,seekBarMarker){
		var cueRange = {start: start, end: end, current: false};
		this.cueRanges[name] = cueRange;
	};
	connector.removeCueRange = function(name){
		delete this.cueRanges[name];
	}
	connector.updateCueRanges = function(){
		for(var i in this.cueRanges){
			if(this.player.videoEl.currentTime > this.cueRanges[i].start && this.player.videoEl.currentTime < this.cueRanges[i].end && !this.cueRanges[i].current){
				this.fireEvent("onCueRangeEnter",'"'+i+'"');
				this.cueRanges[i].current = true;
			}else if((this.player.videoEl.currentTime < this.cueRanges[i].start || this.player.videoEl.currentTime > this.cueRanges[i].end) && this.cueRanges[i].current){
				this.fireEvent("onCueRangeExit",'"'+i+'"');
				this.cueRanges[i].current = false;
			}
		}
	};
	player.videoEl.addEventListener("timeupdate",function(){connector.updateCueRanges();});
	if(!player.eventHandlers){
		player.eventHandlers = {};
	}
	connector.fireEvent = function(name,message){
		if(!this.player.eventHandlers[name]){
			return;
		}
		for(var i = 0;i < this.player.eventHandlers[name].length;i++){
			injectScript(this.player.eventHandlers[name][i] + "(" + message + ");");
		}
	}
	connector.addEventListener = function(name,callback){
		if(!this.player.eventHandlers[name]){
			this.player.eventHandlers[name] = [];
		}
		this.player.eventHandlers[name].push(callback);
	}
	
	injectScript("var arr = ['playVideo','pauseVideo','stopVideo','seekTo','clearVideo','mute','unMute', 'setVolume','setSize','setPlaybackQuality', 'addEventListener', 'addCueRange', 'removeCueRange'];var el = document.getElementById('"+connector.id+"');for(var i = 0; i < arr.length; i++){(function(i){el[arr[i]] = function(){window.postMessage(JSON.stringify({fn: arr[i], target: this.id, args: Array.prototype.slice.call(arguments), action: 'callMethodOfElement'}),'*');};}(i));} el.isMuted = function(){return this.player.videoEl.isMuted;}; el.getVolume = function(){return this.player.videoEl.volume*100;};el.getPlayerState = function(){return this.player.videoEl.state;};el.getCurrentTime = function(){return this.player.videoEl.currentTime;};el.getDuration = function(){return this.player.videoData.duration;};el.getVideoUrl = function(){return 'http://www.youtube.com/watch?v='+this.player.videoData.id;};el.getVideoEmbedCode = function(){return '<object style=\"height: 390px; width: 640px\"><param name=\"movie\" value=\"http://www.youtube.com/watch?v='+this.player.videoData.id+'\"><param name=\"allowFullScreen\" value=\"true\"><param name=\"allowScriptAccess\" value=\"always\"><embed src=\"http://www.youtube.com/watch?v='+this.player.videoData.id+'\" type=\"application/x-shockwave-flash\" allowfullscreen=\"true\" allowScriptAccess=\"always\" width=\"640\" height=\"390\"></object>';};");
	
	return connector;
}

function buildControlsElement(player,videoEl){
	var UIElement = document.createElement("div");
	UIElement.className = "video-UI video-UI-shown";
	var controlsElement = document.createElement("div");
	controlsElement.className = "video-controls";
	
	var scrubber = document.createElement("div");
	var scrubberPlayed = document.createElement("div");
	scrubber.className = "video-scrubber";
	scrubber.addEventListener("mousedown",scrubberMouseDown);
	scrubber.addEventListener("mouseup",scrubberMouseUp);
	scrubber.addEventListener("mouseover",scrubberMouseOver);
	scrubber.addEventListener("mousemove",scrubberMouseMove2);
	scrubber.addEventListener("mouseout",scrubberMouseOut);
	scrubberPlayed.className = "video-scrubber-played";
	scrubber.appendChild(scrubberPlayed);
	UIElement.appendChild(scrubber);
	
	var playButton = document.createElement("div");
	var playImage = document.createElement("div");
	playImage.className = "video-play-image video-controls-image";
	playButton.className = "video-play-button video-controls-button";
	playButton.addEventListener("click",playButtonClicked);
	playButton.appendChild(playImage);
	controlsElement.appendChild(playButton);
	
	var volumeDiv = document.createElement("div");
	var volumeButton = document.createElement("div");
	var volumeImage = document.createElement("div");
	var volumeSlider = document.createElement("div");
	var volumeSliderImage = document.createElement("div");
	volumeDiv.className = "video-volume-div";
	volumeButton.className = "video-volume-button video-controls-button";
	volumeImage.className = "video-volume-image video-volume-max video-controls-image";
	volumeButton.appendChild(volumeImage);
	volumeButton.addEventListener("click",muteVideo);
	volumeSlider.className = "video-volume-slider";
	volumeSliderImage.className = "video-volume-slider-image";
	volumeSliderImage.addEventListener("mousedown",dragVolumeStart,true);
	volumeSliderImage.addEventListener("mouseup",dragVolumeEnd,true);
	volumeSlider.appendChild(volumeSliderImage);
	volumeDiv.appendChild(volumeButton);
	volumeDiv.appendChild(volumeSlider);
	controlsElement.appendChild(volumeDiv);
	
	var timeDiv = document.createElement("div");
	timeDiv.className = "video-times";
	var currentTimeSpan = document.createElement("span");
	currentTimeSpan.className = "video-current-time";
	currentTimeSpan.innerHTML = "00:00";
	var durationSpan = document.createElement("span");
	durationSpan.className = "video-duration";
	if(player.videoData.duration){
		player.duration = player.videoData.duration;
		durationSpan.innerHTML = secondsToMinutes(player.videoData.duration);
	}else{
		durationSpan.innerHTML = "--:--";
	}
	var slashSpan = document.createElement("span");
	slashSpan.className = "video-slash";
	slashSpan.innerHTML = "/";
	timeDiv.appendChild(currentTimeSpan);
	timeDiv.appendChild(slashSpan);
	timeDiv.appendChild(durationSpan);
	controlsElement.appendChild(timeDiv);
	
	
	/*
	// Not yet...
	var speedDiv = document.createElement("div");
	speedDiv.className = "video-speed-div";
	var speedButton = document.createElement("span");
	speedButton.textContent = "Normal";
	
	controlsElement.appendChild(speedDiv);
	*/
	
	var fullButton = document.createElement("div");
	var fullImage = document.createElement("div");
	fullImage.className = "video-small-image video-fullsmall-image video-controls-image";
	fullButton.className = "video-full-button video-controls-button";
	player.className = player.className + " video-small";
	fullButton.addEventListener("click",fullButtonClicked);
	fullButton.appendChild(fullImage);
	controlsElement.appendChild(fullButton);
	
	var wideButton = document.createElement("div");
	var wideImage = document.createElement("div");
	wideImage.className = "video-wide-image video-widesmall-image video-controls-image";
	wideButton.className = "video-wide-button video-controls-button";
	
	var tooltip = document.createElement("div");
	var tooltipArrow = document.createElement("div");
	var tooltipBody = document.createElement("div");
	var tooltipContent = document.createElement("div");
	
	tooltip.className = "tooltip";
	tooltipArrow.className = "tooltip-arrow";
	tooltipBody.className = "tooltip-body";
	tooltipContent.className = "tooltip-content";
	tooltipContent.innerHTML = "00:00";
	
	tooltip.appendChild(tooltipBody);
	tooltipBody.appendChild(tooltipContent);
	tooltip.appendChild(tooltipArrow);
	UIElement.appendChild(tooltip);
	
	if(videoEl.srcList){
		var qualityDiv = document.createElement("div");
		qualityDiv.className = "video-quality-div";
		
		var qualityButton = document.createElement("span");
		qualityButton.className = "video-quality-button";
		qualityButton.innerHTML = videoEl.currentQuality.type.name;
		qualityButton.addEventListener("click",toggleQualityMenu,false);
		qualityDiv.appendChild(qualityButton);
		
		var qualityList = document.createElement("ul");
		qualityList.className = "video-quality-list";
		for(var l = 0; l < videoEl.srcList.length; l++){
			var fmt = videoEl.srcList[l];
			var fmtLi = document.createElement("li");
			fmtLi.className = "video-format-item video-format-"+fmt.type.type+" video-format-HD-"+fmt.type.HD;
			fmtLi.innerHTML = fmt.type.name;
			fmtLi.fmt = fmt;
			fmtLi.addEventListener("click",switchQuality,false);
			qualityList.appendChild(fmtLi);
		}
		
		qualityDiv.appendChild(qualityList);
		
		controlsElement.appendChild(qualityDiv);
	}
	
	if(videoEl.hasAnnotations){
		var annotationsDiv = document.createElement("div");
		annotationsDiv.className = "video-annotations-div";
		
		var annotationsImage = document.createElement("div");
		annotationsImage.className = "video-annotations-image enabled";
		annotationsDiv.addEventListener("click",toggleAnnotations,false);
		annotationsDiv.appendChild(annotationsImage);
		
		controlsElement.appendChild(annotationsDiv);
	}
	
	window.addEventListener("resize",function(){fullButtonClicked(player);},false);
	
	player.addEventListener("mouseover",videoMouseOver,false);
	player.addEventListener("mouseout",videoMouseOut,false);
	player.addEventListener("mousemove",videoMouseMove,false);
	videoEl.addEventListener("progress",updateProgress,false);
	videoEl.addEventListener("playing",videoPlaying,false);
	videoEl.addEventListener("pause",videoPaused,false);
	videoEl.addEventListener("timeupdate",videoTimeUpdate,false);
	videoEl.addEventListener("ended",videoEnded,false);
	videoEl.addEventListener("volumechange",videoVolumeChanged,false);
	videoEl.addEventListener("durationchange",videoDurationChanged,false);
	videoEl.addEventListener("loadeddata",videoLoaded,false);
	videoEl.isPlaying = false;
	
	UIElement.appendChild(controlsElement);
	
	return UIElement;
}

function secondsToMinutes(seconds){
	var secs = Math.round(seconds%60)
	var minutes = Math.floor(seconds/60);
	var hours = Math.floor(minutes/60);
	minutes = minutes % 60;
	if(hours){
		return hours+":"+zeroPad(minutes,2)+":"+zeroPad(Math.round(seconds%60),2);
	}
	return zeroPad(minutes,2)+":"+zeroPad(Math.round(seconds%60),2);
}

function scrubberMouseMove2(event){
	var scrubberWidth = parseInt(this.computedStyle.width);
	var scrubberMouse = event.offsetX;
	var scrubberRight = scrubberWidth - scrubberMouse;
	var percent = scrubberMouse/scrubberWidth;
	var videoEl = this.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	var duration = videoEl.duration;
	var newTime = percent*duration;
	var tooltipDiv = this.parentNode.parentNode.parentNode.getElementsByClassName("tooltip")[0];
	if(duration){
		tooltipDiv.getElementsByClassName("tooltip-content")[0].innerHTML = secondsToMinutes(newTime);
	}else{
		tooltipDiv.getElementsByClassName("tooltip-content")[0].innerHTML = "--:--";
	}
	tooltipDiv.getElementsByClassName("tooltip-arrow")[0].style.left = parseInt(tooltipDiv.getElementsByClassName("tooltip-body")[0].computedStyle.width)/2-5+"px";
	if(scrubberMouse-(parseInt(tooltipDiv.getElementsByClassName("tooltip-body")[0].computedStyle.width)/2) < 0){
		tooltipDiv.style.left = "0px";
		tooltipDiv.getElementsByClassName("tooltip-arrow")[0].style.left = scrubberMouse - 5 + "px";
		if(scrubberMouse < 10){
			if(scrubberMouse > 4){
				tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomLeftRadius = "5px " + (scrubberMouse-5) + "px";
			}else{
				tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomLeftRadius = "5px 0px";
			}
		}else{
			tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomLeftRadius = "5px 5px";
		}
		tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomRightRadius = "5px 5px";
	}else if(scrubberMouse+(parseInt(tooltipDiv.getElementsByClassName("tooltip-body")[0].computedStyle.width)/2) > scrubberWidth){
		tooltipDiv.style.left = scrubberWidth-parseInt(tooltipDiv.getElementsByClassName("tooltip-body")[0].computedStyle.width)+"px";
		tooltipDiv.getElementsByClassName("tooltip-arrow")[0].style.left = ((scrubberMouse - scrubberWidth+parseInt(tooltipDiv.getElementsByClassName("tooltip-body")[0].computedStyle.width)) - 5) + "px";
		if(scrubberRight < 10){
			if(scrubberRight > 4){
				tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomRightRadius = "5px " + (scrubberRight-5) + "px";
			}else{
				tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomRightRadius = "5px 0px";
			}
		}else{
			tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomRightRadius = "5px 5px";
		}
		tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomLeftRadius = "5px 5px";
	}else{
		tooltipDiv.style.left = scrubberMouse-(parseInt(tooltipDiv.getElementsByClassName("tooltip-body")[0].computedStyle.width)/2)+"px";
		tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomLeftRadius = "5px 5px";
		tooltipDiv.getElementsByClassName("tooltip-content")[0].style.borderBottomRightRadius = "5px 5px";
	}
}

function scrubberMouseOver(event){
	var tooltipDiv = this.parentNode.parentNode.parentNode.getElementsByClassName("tooltip")[0];
	tooltipDiv.style.opacity = "1";
	tooltipDiv.style.display = "inline-block";
}

function scrubberMouseOut(event){
	var tooltipDiv = this.parentNode.parentNode.parentNode.getElementsByClassName("tooltip")[0];
	tooltipDiv.style.opacity = "0";
	tooltipDiv.style.display = "none";
	this.removeEventListener("mousemove",scrubberMouseMove);
}

function switchQualityToFmt(fmt,vidEl){
	var fmtType = fmt.type,
		fmtUrl = fmt.url,
		statEl = vidEl.parentNode.parentNode.getElementsByClassName("video-quality-button")[0];
	statEl.innerHTML = fmtType.name;
	if(vidEl.isPlaying){
		vidEl.pause();
		vidEl.autoplay = true;
	}
	vidEl.jumpTime = vidEl.currentTime;
	vidEl.preload = "auto";
	vidEl.src = fmtUrl;
	updateProgress(vidEl);
}

function switchQuality(){
	var fmtType = this.fmt.type;
	var fmtUrl = this.fmt.url;
	var statEl = this.parentNode.parentNode.getElementsByClassName("video-quality-button")[0];
	this.parentNode.style.display = "none";
	statEl.innerHTML = fmtType.name;
	var videoEl = this.parentNode.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	if(videoEl.isPlaying){
		videoEl.pause();
		videoEl.autoplay = true;
	}
	videoEl.jumpTime = videoEl.currentTime;
	videoEl.preload = "auto";
	videoEl.src = fmtUrl;
	updateProgress(videoEl);
}

function toggleQualityMenu(){
	var qualityMenu = this.parentNode.getElementsByTagName("ul")[0];
	if(qualityMenu.style.display == "block"){
		qualityMenu.style.display = "none";
	}else{
		qualityMenu.style.display = "block";
	}
}

function muteVideo(){
	var videoEl = this.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	if(videoEl.muted){
		videoEl.muted = false;
	}else{
		videoEl.muted = true;
	}
}

function dragVolumeStart(event){
	this.addEventListener("mousemove",dragVolume,false);
	var videoEl = this.parentNode.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	videoEl.volume = Math.round((event.offsetX/(parseInt(this.computedStyle.width)+2))*100)/100;
	videoEl.muted = false;
}

function dragVolume(event){
	var videoEl = this.parentNode.parentNode.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	videoEl.volume = Math.round((event.offsetX/(parseInt(this.computedStyle.width)+2))*100)/100;
	videoEl.muted = false;
}

function dragVolumeEnd(){
	this.removeEventListener("mousemove",dragVolume,false);
}

function videoLoaded(this2){

	var ratioList = [2.39,2,1.85,6/7,16/9,3/2,4/3,5/4,1,9/16];
	
	if(!this2.parentNode){
		this2 = this;
	}
	
	var contentDiv = this2.parentNode;
	var playerDiv = contentDiv.parentNode;
	var videoEl = this2;
	
	this.loaded = true;
	
	playerDiv.videoData.duration = this2.duration;
	
	contentDiv.classList.add("full");
	contentDiv.classList.remove("shrunk");
	contentDiv.style.setProperty("-webkit-transform","");
	
	contentDiv.style.width = contentDiv.parentNode.computedStyle.width;
	contentDiv.style.height = contentDiv.parentNode.computedStyle.height;

	var videoWidth = videoEl.videoWidth;
	var videoHeight = videoEl.videoHeight;
	var videoRatio = videoWidth/videoHeight; 
	//var videoRatio = roundToArray(videoWidth/videoHeight,ratioList);
	var containerWidth = parseInt(contentDiv.style.width);
	var containerHeight = parseInt(contentDiv.style.height);
	var containerRatio = containerWidth/containerHeight;
	
	contentDiv.ratio = videoRatio;
	
	if(containerRatio > videoRatio){
		playerDiv.style.height = contentDiv.style.height = containerHeight + "px";
		playerDiv.style.width = contentDiv.style.width = containerHeight * videoRatio + "px";
	}else if(containerRatio < videoRatio){
		playerDiv.style.width = contentDiv.style.width = containerWidth + "px";
		playerDiv.style.height = contentDiv.style.height = containerWidth / videoRatio + "px";
	}else{
		playerDiv.style.width = contentDiv.style.width = containerWidth + "px";
		playerDiv.style.height = contentDiv.style.height = containerHeight + "px";
	}
	
	contentDiv.classList.add("full");
	contentDiv.classList.remove("shrunk");
	contentDiv.style.setProperty("-webkit-transform","scaleY("+(1-(38/parseInt(playerDiv.computedStyle.height)))+") translateY(-21px)");
	
	this2.apiConnector.setPlayerState(5);
}

function scrubberMouseDown(event){
	this.addEventListener("mousemove",scrubberMouseMove);
	var scrubberWidth = this.scrollWidth;
	var scrubberMouse = event.offsetX + parseInt(event.target.style.left,10);
	var percent = scrubberMouse/scrubberWidth;
	var videoEl = this.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	var duration = videoEl.parentNode.parentNode.videoData.duration;
	var newTime = percent*duration;
	if(videoEl.ended){
		this.parentNode.parentNode.getElementsByClassName("video-play-image")[0].className = this.parentNode.parentNode.getElementsByClassName("video-play-image")[0].className.replace("play","pause");
		videoEl.isPlaying = true;
	}
	try{
		videoEl.currentTime = newTime+videoEl.startTime;
	}catch(e){
		
	}
}

function scrubberMouseUp(event){
	this.removeEventListener("mousemove",scrubberMouseMove);
}

function scrubberMouseMove(event){
	var scrubberWidth = this.scrollWidth;
	var scrubberMouse = event.offsetX + parseInt(event.target.style.left,10);
	var percent = scrubberMouse/scrubberWidth;
	var videoEl = this.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	var duration = videoEl.parentNode.parentNode.videoData.duration;
	var newTime = percent*duration;
	videoEl.currentTime = newTime+videoEl.startTime;
}

function playButtonClicked(){
	var videoElement = this.parentNode.parentNode.parentNode.getElementsByTagName("video")[0];
	var isPlaying = videoElement.isPlaying;
	if(videoElement.ended){
		this.childNodes[0].className = this.childNodes[0].className.replace("video-play-image","video-pause-image");
		videoElement.isPlaying = true;
		// Normally, the last 2 lines are covered by the playing event handler, but there's something messed up in it when .ended is true.
	}
	if(!isPlaying){
		videoElement.play();
	}else{
		videoElement.pause();
	}
}

function fullButtonClicked(event,force){
	var videoElement;
	if(event.parentNode){
		this2 = event;
		event = false;
		videoElement = this2;
	}else{
		this2 = this;
		videoElement = this2.parentNode.parentNode.parentNode;
	}
	var vidEl = videoElement.getElementsByTagName("video")[0];
	
	var sw = false;
	
	if(vidEl.hasAnnotations && !event.altKey || ('webkitRequestFullScreen' in videoElement)){
		var imageElement = this2.getElementsByClassName("video-fullsmall-image")[0];
		var wasPlaying = vidEl.isPlaying;
		if(event || force){
			if(videoElement.className.indexOf("video-full-window") == -1){
				sw = true;
				videoElement.originalWidth = videoElement.computedStyle.width;
				videoElement.originalHeight = videoElement.computedStyle.height;
				videoElement.className = videoElement.className.replace("video-small","video-full-window");
				imageElement.className = imageElement.className.replace("video-small-image","video-full-image");
				if('webkitRequestFullScreen' in videoElement){
					videoElement.webkitRequestFullScreen();
				}else{
					document.body.className+= " body-full-window";
				}
			}else{
				if(videoElement.webkitIsFullScreen){
					document.webkitCancelFullScreen();
				}
				injectScript("if(window.checkCurrentVideo){checkCurrentVideo('"+videoElement.videoData.id+"');}");
				videoElement.className = videoElement.className.replace("video-full-window","video-small");
				imageElement.className = imageElement.className.replace("video-full-image","video-small-image");
				document.body.className = document.body.className.replace(/body-full-window/gi,"")
				videoElement.style.width = videoElement.originalWidth;
				videoElement.style.height = videoElement.originalHeight;
			}
		}
		
		var videoEl = videoElement.getElementsByTagName("video")[0];
		var contentDiv = videoElement.getElementsByClassName("video-player-content")[0];
		
		contentDiv.style.width = "";
		contentDiv.style.height = "";
		
		var videoWidth = videoEl.videoWidth;
		var videoHeight = videoEl.videoHeight;
		var videoRatio = videoWidth/videoHeight;
		var containerWidth = contentDiv.scrollWidth;
		var containerHeight = contentDiv.scrollHeight;
		var containerRatio = containerWidth/containerHeight;
		
		contentDiv.ratio = videoRatio;
		
		if(containerRatio > videoRatio){
			contentDiv.style.height = containerHeight + "px";
			contentDiv.style.width = containerHeight * videoRatio + "px";
		}else if(containerRatio < videoRatio){
			contentDiv.style.width = containerWidth + "px";
			contentDiv.style.height = containerWidth / videoRatio + "px";
		}else{
			contentDiv.style.width = containerWidth + "px";
			contentDiv.style.height = containerHeight + "px";
		}
		if(sw){
			var qualities = vidEl.srcList;
			var bestFmt = getFormatForRect(qualities,{width: parseInt(vidEl.computedStyle.width), height: parseInt(vidEl.computedStyle.height)});
			if(bestFmt.url != vidEl.src){
				switchQualityToFmt(bestFmt,vidEl);
			}
		}
	}else{
		vidEl.webkitEnterFullscreen();
	}
}

function videoMouseMove(){
	var videoUI = this.getElementsByClassName("video-UI")[0];
	videoUI.className = videoUI.className.replace("video-UI-hidden", "video-UI-shown");
	
	var mouseOverEvent=document.createEvent("MouseEvents");mouseOverEvent.initEvent("mouseover", true, true);this.dispatchEvent(mouseOverEvent);
	
	clearTimeout(this.timeout);
	this.timeout = setTimeout(function(thisObj){var mouseOutEvent=document.createEvent("MouseEvents");mouseOutEvent.initEvent("mouseout", true, true);thisObj.dispatchEvent(mouseOutEvent);},5000,this);
}

function videoMouseOver(event){
	
	var contentDiv = this.getElementsByClassName("video-player-content")[0];
	var videoEl = this.getElementsByTagName("video")[0];
	
	if(contentDiv.className.indexOf("full") != -1 && (!event.relatedTarget || !event.relatedTarget.isAncestor(this)) && videoEl.loaded){
		contentDiv.style.setProperty("-webkit-transform","scaleY("+(1-(38/parseInt(this.computedStyle.height)))+") translateY(-21px)");
		contentDiv.className = contentDiv.className.replace("full","shrunk");
	}
	
	var videoUI = this.getElementsByClassName("video-UI")[0];
	videoUI.className = videoUI.className.replace("video-UI-hidden", "video-UI-shown");
	clearTimeout(this.timeout);
	this.timeout = setTimeout(function(thisObj){var mouseOutEvent=document.createEvent("MouseEvents");mouseOutEvent.initEvent("mouseout", true, true);thisObj.dispatchEvent(mouseOutEvent);},5000,this);
}

function videoMouseOut(event){
	var contentDiv = this.getElementsByClassName("video-player-content")[0];
	var videoElement = this.getElementsByTagName("video")[0];
	var videoUI = this.getElementsByClassName("video-UI")[0];
	if(videoElement.isPlaying){
		contentDiv.style.setProperty("-webkit-transform","");
		contentDiv.className = contentDiv.className.replace("shrunk","full");
		videoUI.className = videoUI.className.replace("video-UI-shown", "video-UI-hidden");
	}
}

function videoVolumeChanged(){
	if(this.muted || this.volume == 0){
		this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className = this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className.replace(/max|loud|normal|quiet|min|off/,"off");
		this.parentNode.parentNode.getElementsByClassName("video-volume-slider-image")[0].style.backgroundPositionX = "-48px";
		return;
	}else if(this.volume < 0.2){
		this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className = this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className.replace(/max|loud|normal|quiet|min|off/,"min");
	}else if(this.volume < 0.4){
		this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className = this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className.replace(/max|loud|normal|quiet|min|off/,"quiet");
	}else if(this.volume < 0.6){
		this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className = this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className.replace(/max|loud|normal|quiet|min|off/,"normal");
	}else if(this.volume < 0.8){
		this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className = this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className.replace(/max|loud|normal|quiet|min|off/,"loud");
	}else{
		this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className = this.parentNode.parentNode.getElementsByClassName("video-volume-image")[0].className.replace(/max|loud|normal|quiet|min|off/,"max");
	}
	this.parentNode.parentNode.getElementsByClassName("video-volume-slider-image")[0].style.backgroundPositionX = (-48 + (this.volume * 48)) + "px";
}

function videoPlaying(){
	this.isPlaying = true;
	this.ended = false;
	clearTimeout(this.updatePauseAnnTimeout);
	clearTimeout(this.playTimeout);
	if(this.parentNode.getElementsByClassName("video-annotation-pause")[0]){
		this.parentNode.removeChild(this.parentNode.getElementsByClassName("video-annotation-pause")[0])
	}
	var playImage = this.parentNode.parentNode.getElementsByClassName("video-play-image")[0];
	if(playImage){
		playImage.className = playImage.className.replace("video-play-image","video-pause-image");
	}
	this.apiConnector.setPlayerState(1);
	this.timeout = setTimeout(function(thisObj){var mouseOutEvent=document.createEvent("MouseEvents");mouseOutEvent.initEvent("mouseout", true, true);thisObj.dispatchEvent(mouseOutEvent);},5000,this);
}

function videoPaused(){
	this.isPlaying = false;
	var pauseImage = this.parentNode.parentNode.getElementsByClassName("video-pause-image")[0];
	if(pauseImage){
		pauseImage.className = pauseImage.className.replace("video-pause-image","video-play-image");
	}
	this.apiConnector.setPlayerState(2);
}

function updateProgress(this2){
	if(!this2.parentNode){
		this2 = this;
	}
	var timeRanges = this2.buffered;
	var scrubber = this2.parentNode.parentNode.getElementsByClassName("video-scrubber")[0];
	var scrubberDivs = this2.parentNode.parentNode.getElementsByClassName("video-scrubber-loaded");
	var duration = this2.duration;
	var startTime = this2.startTime;
	var j = 0;
	while(timeRanges.length < this2.parentNode.parentNode.getElementsByClassName("video-scrubber-loaded").length){
		scrubber.removeChild(scrubberDivs[j]);
		j++;
	}
	for(var i = 0; i < timeRanges.length; i++){
		var start = ((timeRanges.start(i) - startTime)/duration)*100;
		var end = 100 - ((timeRanges.end(i) - startTime)/duration)*100;
		if(scrubberDivs[i]){
			var scrubberDiv = scrubberDivs[i];
		}else{
			var scrubberDiv = document.createElement("div");
			scrubberDiv.className = "video-scrubber-loaded";
			scrubber.appendChild(scrubberDiv);
		}
		scrubberDiv.style.left = start + "%";
		scrubberDiv.style.right = end + "%";
	}
}

function videoTimeUpdate(){
	clearTimeout(this.updatePauseAnnTimeout);
	clearTimeout(this.playTimeout);
	if(this.parentNode.getElementsByClassName("video-annotation-pause")[0]){
		this.parentNode.removeChild(this.parentNode.getElementsByClassName("video-annotation-pause")[0])
	}
	var duration = this.duration;
	var startTime = this.startTime;
	var currentTime = this.currentTime;
	this.parentNode.parentNode.getElementsByClassName("video-current-time")[0].innerText = secondsToMinutes(currentTime);
	var scrubberDiv = this.parentNode.parentNode.getElementsByClassName("video-scrubber-played")[0];
	var current = 100 - ((currentTime - startTime)/duration)*100;
	scrubberDiv.style.right = current + "%";
	this.ended = false;
	updateProgress(this);
}

function videoDurationChanged(){
	this.parentNode.parentNode.getElementsByClassName("video-duration")[0].innerText = secondsToMinutes(this.duration);
}

function videoEnded(){
	this.isPlaying = false;
	this.ended = true;
	var mouseOverEvent=document.createEvent("MouseEvents");
	mouseOverEvent.initEvent("mouseover", true, true);
	this.parentNode.parentNode.dispatchEvent(mouseOverEvent);
	var playImage = this.parentNode.parentNode.getElementsByClassName("video-pause-image")[0];
	if(playImage){
		playImage.className = playImage.className.replace("video-pause-image","video-play-image");
	}
	if(!this.playlistIncrement){
		this.playlistIncrement = 1;
	}
	this.apiConnector.cueRanges = {};
	if(this.parentNode.parentNode.className.indexOf("video-full-window") != -1){
		var fn = function(vidElId,playlistIncrement){
			if(window.getNextVideoId){
				window.postMessage(JSON.stringify({fn: "nextVideo", args: [vidElId,getNextVideoId(playlistIncrement)], action: "callFunction"}),"*");
			}else{
				window.postMessage(JSON.stringify({fn: "finishVideo", args: [vidElId], action: "callFunction"}),"*");
			}
		};
		injectScript("var fn = "+fn.toString()+"; fn('"+this.id+"',"+this.playlistIncrement+");");
	}else{
		finishVideo(this);
	}
}

function nextVideo(vidEl,nextId){
	if(typeof vidEl == "string"){
		vidEl = document.getElementById(vidEl);
	}
	vidEl.jumpTime = 0;
	vidEl.playlistIncrement++;
	var video = {
		id: nextId,
		playerId: vidEl.player.id,
		flashVars: {}
	};
	vidEl.autoplay = true;
	safari.self.tab.dispatchMessage("loadNextYouTubeVideo",video);
}

function finishVideo(vidEl){
	if(typeof vidEl == "string"){
		vidEl = document.getElementById(vidEl);
	}
	if(vidEl.parentNode.parentNode.className.indexOf("video-full-window") != -1){
		var mouseDownEvent=document.createEvent("MouseEvents");
		mouseDownEvent.initEvent("click", true, true);
		vidEl.parentNode.parentNode.getElementsByClassName("video-full-button")[0].dispatchEvent(mouseDownEvent);
	}
	vidEl.apiConnector.setPlayerState(0);
}

function jumpToTime(){
	try{
		this.currentTime = this.jumpTime;
	}catch(e){
		// Try-Catch-Gulp because this exception is only due to a Perian issue.
	}
}

function buildAudioPlayer(audioURL, replace, autoplay) {
	if(typeof(replace) == "string"){
		replace = document.getElementById(replace);
	}
	if(typeof autoplay == "string"){
		if(autoplay == "true" || autoplay == "t" || autoplay == "1" || autoplay == "yes"){
			autoplay = true;
		}else{
			autoplay = false;
		}
	}else if(typeof autoplay == "boolean"){
		
	}else if(typeof autoplay == "number"){
		if(autoplay == 1){
			autoplay = true;
		}else{
			autoplay = false;
		}
	}else{
		autoplay = false;
	}
	
	if(replace.className.indexOf("no-load-video") != -1){
		return false;
	}
	var player = document.createElement('div');

	if(typeof(replace) == "string"){
		replace = document.getElementById(replace);
	}

	player.className = 'html5-audio-player';

	if (autoplay) {
		player.className += ' html5-audio-autoplay';
	}
	
	if(replace.parentNode.nodeName=="OBJECT"){
		replace = replace.parentNode;
	}

	player.id = 'html5-audio-player-' + Math.uuid(2,16);

	player.style.width = replace.scrollWidth+"px";
	player.style.height = replace.scrollHeight+"px";
	
	var audioEl = document.createElement('audio');

	audioEl.src = audioURL;
	audioEl.style.width = "100%";
	audioEl.style.height = "100%";
	audioEl.controls = true;

	if (autoplay) {
		audioEl.autoplay = true;
	} else {
		audioEl.preload = "none";
	}

	player.appendChild(audioEl);
	
	replace.style.display = "none";
	
	replace.parentNode.insertAfter(player,replace);
}

function restoreVideo(id){
	var el = document.getElementById(id);
	if(el){
		if(el.player){
			el = el.player;
		}
		el.apiConnector.className = el.apiConnector.className.replace(/YouTube\-API\-Connector/g, "");
		el.parentNode.removeChild(el);
	}
}

function buildServicePlayer(videoId, replace, autoplay, service, flashVars, siteURL){
	
	if(typeof(replace) == "string"){
		replace = document.getElementById(replace);
	}
	if(typeof autoplay == "string"){
		if(autoplay == "true" || autoplay == "t" || autoplay == "1" || autoplay == "yes"){
			autoplay = true;
		}else{
			autoplay = false;
		}
	}else if(typeof autoplay == "boolean"){
		
	}else if(typeof autoplay == "number"){
		if(autoplay == 1){
			autoplay = true;
		}else{
			autoplay = false;
		}
	}else{
		autoplay = false;
	}
	if(replace.className.indexOf("no-load-video") != -1){
		return false;
	}
	var player = document.createElement('div');

	player.className = 'html5-video-player';

	if (autoplay) {
		player.className += ' html5-video-autoplay html5-video-loading';
	}
	
	if(replace.parentNode.nodeName=="OBJECT"){
		replace = replace.parentNode;
	}

	var playerUUID = Math.uuid(2,16);

	player.id = 'html5-video-player-' + playerUUID;
	
	player.playerId = playerUUID;

	videos[player.id] = replace;
	
	var width = replace.computedStyle.width;
	var height = replace.computedStyle.height;

	if(!width || !height){
		player.style.width = "100%";
		player.style.height = "100%";
	}else{
		player.style.width = width;
		player.style.height = height;
	}
	
	var video = {
		id: videoId,
		playerId: player.id,
		flashVars: flashVars,
		replaceId: replace.id,
		service: service,
		siteURL: siteURL
	};
	
	player.originalPlugin = replace;
	
	var parent = replace.parentNode;
	while(parent.computedStyle && (parent.computedStyle.height == replace.computedStyle.height)){
		parent.style.height = "initial";
		parent.style.minHeight = "initial";
		parent = parent.parentNode;
	}
	
	replace.className = "YouTube-API-Connector no-load-video";
	
	player.apiConnector = replace;
	
	replace.parentNode.insertAfter(player, replace);
	
	switch(service.toLowerCase()){
		case "vimeo":
			safari.self.tab.dispatchMessage("loadVimeo", video);
		break;
		case "collegehumor":
			safari.self.tab.dispatchMessage("loadCollegeHumor", video);
		break;
		case "megavideo":
			safari.self.tab.dispatchMessage("loadMegaVideo", video);
		break;
		case "veoh":
			safari.self.tab.dispatchMessage("loadVeoh", video);
		break;
		case "jibjab":
			safari.self.tab.dispatchMessage("loadJibJab",video);
		break;
		case "jw":
			safari.self.tab.dispatchMessage("loadJW",video);
		break;
		case "ign":
			safari.self.tab.dispatchMessage("loadIGN",video);
		break;
		case "youtube":
			if(window.location.href.indexOf("/watch?") != -1){
			//	player.style.width = "854px";
			//	player.style.height = "480px";
			//	player.style.margin = "auto";
			//	player.parentNode.style.height = "480px";
			}
			safari.self.tab.dispatchMessage("loadVideo", video);
		break;
		case "url":
		default:
			if(flashVars){
				if(flashVars.thumbnailUrl){
					video.posterFrame = flashVars.thumbnailUrl;
				}else if(flashVars.thumb_url){
					video.posterFrame = flashVars.thumb_url;
				}
			}
			video.src = videoId;
			injectVideo(video);
		break;
	}
}

function getVideoFromDMSequence(sequence){
	var videoVersions = [];
	var matches;
	if(supportsFLV){
		matches = sequence.match(/\"sdURL\":\"([^"]*)\"/);
		if(matches){
			videoVersions.push({fmt: -1, url: matches[1].replace(/\\\//g,"/"), type: {name: "240p", type:"FLV", HD: false}});
		}
	}
	matches = sequence.match(/\"hqURL\":\"([^"]*)\"/);
	if(matches){
		videoVersions.push({fmt: -1, url: matches[1].replace(/\\\//g,"/"), type: {name: "480p", type:"MP4", HD: false}});
	}
	matches = sequence.match(/\"hdURL\":\"([^"]*)\"/);
	if(matches){
		videoVersions.push({fmt: -1, url: matches[1].replace(/\\\//g,"/"), type: {name: "720p", type:"MP4", HD: true}});
	}
	return videoVersions;
}

function getVideoFromMegavideo(video){
	var str_bin = "";
	//1. Convert hex "un" to binary
	for(var i = 0; i < video.un.length; i++){
		str_bin = str_bin + zeroPad(parseInt(video.un.charAt(i),16).toString(2),4);
	}
	var arr_bin = str_bin.split("");
	//2. Generate and switch XOR keys
	var key = Array();
	var key1 = video.k1;
	var key2 = video.k2;
	for(var x = 0; x < 384; x++){
		key1 = (key1 * 11 + 77213) % 81371;
		key2 = (key2 * 17 + 92717) % 192811;
		key[x] = ( key1 + key2 ) % 128;
	}
	//3. Switch bits positions
	for(var y = 256; y >= 0; y--){
		var temp = arr_bin[key[y]];
		arr_bin[key[y]] = arr_bin[y%128];
		arr_bin[y%128] = temp;
	}
	//4. XOR entire binary string
	for(var z = 0; z < 128; z++){
		arr_bin[z] = arr_bin[z] ^ key[z+256] & 1;
	}
	//5. Convert binary string back to hex
	str_bin = arr_bin.join("");
	var str_hex = "";
	for(var j = 0; j < 32; j++){
		str_hex = str_hex + parseInt(str_bin.substr(j*4,4),2).toString(16);
	}
	return "http://www"+video.s+".megavideo.com/files/"+str_hex+"/video.flv";
}

function injectHTML5Video(message) {
	if(window.location.href.indexOf("youtube.com/watch") != -1){
		if(document.getElementById("watch-video")){
//			document.getElementById("watch-video").className = "wide";
		}
		if(document.getElementById("content")){
//			document.getElementById("content").className = "watch-wide";
		}
	}
	if(!message){
		return;
	}
	var embed = document.getElementById(message);
	if(!embed){
		return;
	}
	if(embed.nodeName == "EMBED"){
		if(embed.processed){
			return;
		}
		embed.processed = true;
		if(embed.parentNode.nodeName == "OBJECT"){
			return;
		}
		var newFlashVars = embed.src.between("?",false);
		newFlashVars = newFlashVars + "&" + embed.getAttribute("flashvars");
		var originalSrc = embed.src;
		var src = originalSrc.between(false,"?");
		if(src.indexOf("&") != -1){
			newFlashVars = src.between("&",false) + "&" + newFlashVars;
			src = src.between(false,"&");
		}
		while(newFlashVars.indexOf("&&") != -1){
			newFlashVars = newFlashVars.replace(/&&/g,"&");
		}
		var flashVarsArray = getQueryString(newFlashVars);
		var flashObject = {
			src: src,
			originalSrc: originalSrc,
			flashVarsString: newFlashVars,
			flashVars: flashVarsArray,
			id: embed.id,
			originalPlugin: embed,
			type: embed.getAttribute("type"),
			elementName: "EMBED"
		};
	}else if(embed.nodeName == "OBJECT"){
		var newFlashVars = "";
		if(embed.getAttribute("data")){
			newFlashVars = newFlashVars + embed.getAttribute("data").between("?",false);
		}
		newFlashVars = newFlashVars + "&" + embed.getParamByName("flashvars").value;
		newFlashVars = newFlashVars + "&" + embed.getParamByName("movie").value.between("?",false);
		newFlashVars = newFlashVars + "&" + embed.getParamByName("src").value.between("?",false);
		var src;
		// I hate how many ways there have to be to add flashvars, and even to define the freaking URL where the file is!
		// How complex is it to have a src attribute and a flashvars attribute!?
		// And then there's the <param> tag. I mean, who's idea was that?
		// We can define attributes within the <object> tag, you know!
		// And then there's the MS pseudo-standard <embed> tag. Sure, the <object> tag sucked and, true, <embed> is a better implementation.
		// But still! We don't need two tags for it, and much less one embedded within another!
		// Phew, blew off some steam. Well, I hope anyone who reads this agrees. Back to giving myself an easy way around it!
		if(embed.getAttribute("data")){
			src = embed.getAttribute("data").between(false,"?");
		}else if(embed.getParamByName("filename").value){
			src = embed.getParamByName("filename").value.between(false,"?");
		}else if(embed.getParamByName("movie").value){
			src = embed.getParamByName("movie").value.between(false,"?");
		}else if(embed.getAttribute("src")){
			src = embed.getAttribute("src").between(false,"?");
		}else if(embed.getParamByName("src").value){
			src = embed.getParamByName("src").value.between(false,"?");
		}else if(embed.getEmbed() && embed.getEmbed().src){
			newFlashVars = newFlashVars + "&" + embed.getEmbed().src.between("?",false);
			src = embed.getEmbed().src.between(false,"?");
		}
		if(!src){
			return;
		}
		if(src.indexOf("&") != -1){
			newFlashVars = src.between("&",false) + "&" + newFlashVars;
			src = src.between(false,"&");
		}
		//Some string conditioning on newFlashVars
		while(newFlashVars.indexOf("&&") != -1){
			newFlashVars = newFlashVars.replace(/&&/g,"&");
		}
		//Convert the string to an array
		var flashVarsArray = getQueryString(newFlashVars);
		//Make an object out of it all that makes sense
		var flashObject = {
			src: src,
			flashVarsString: flashVars,
			flashVars: flashVarsArray,
			id: embed.id,
			originalPlugin: embed,
			type: embed.getParamByName("type").value,
			elementName: "OBJECT"
		};
		if(!flashObject.type && embed.getEmbed()){
			flashObject.type = embed.getEmbed().getAttribute("type");
		}
	}else{
		return;
	}
	
	var flashVars = flashObject.flashVars;
	var src = flashObject.src;
	var originalPlugin = flashObject.originalPlugin;
	var id = flashObject.id;
	var type = flashObject.type;
	
	if(type === "text/xml"){
		return;
	}
	
	// Directly embedded QuickTime videos (lrn2html5)
	// DISABLED until I figure out how to detect QTVR panoramas
	/*
	if(type == "video/quicktime"){
		buildServicePlayer(src,originalPlugin,originalPlugin.getAttribute("autoplay"),"url",flashVars);
		continue;
	}
	*/
	// AVI directly embedded
	if(src.indexOf(".avi") != -1){
		if(supportsAVI){
			buildServicePlayer(originalSrc,originalPlugin,originalPlugin.getAttribute("autoplay"),"url",flashVars);
		}
		return;
	}
	// WMV directly embedded
	if(src.indexOf(".wmv") != -1 || type == "video/wmv"){
		if(supportsWMV){
			buildServicePlayer(originalSrc,originalPlugin,originalPlugin.getAttribute("autoplay"),"url",flashVars);
			return;
		}
	}
	// WAV Directly Embedded
	if(src.indexOf(".wav") != -1 || type == "audio/wav"){
		if(supportsWAV && false){
			buildAudioPlayer(originalSrc,originalPlugin,originalPlugin.getAttribute("autoplay"));
			return;
		}
	}
	// Facebook player
	if(flashVars.video_src){
		if(supportsFLV){
			buildServicePlayer(flashVars.video_src,originalPlugin,flashVars.video_autoplay,"url",flashVars);
			return;
		}
	}
	// Another Facebook player
	if(flashVars.lowqual_src){
		var src = flashVars.highqual_src ? flashVars.highqual_src : flashVars.lowqual_src;
		buildServicePlayer(src,originalPlugin,flashVars.video_autoplay,"url",flashVars);
		return;
	}
	// DM Video Player
	if(flashVars.source){
		if(supportsFLV){
			buildServicePlayer(flashVars.source,originalPlugin,false,"url",flashVars); // This player seems to default to autoplaying, but most users seem to dislike that, so I'm changing it to false
			return;
		}
	}
	// G4 TV
	if(src.indexOf("g4tv.com/lv3/") != -1){
		if(supportsFLV){
			buildServicePlayer(src.between("/lv3/","/"),originalPlugin,false,"g4tv",flashVars);
		}
	}
	// JW Player
	if(flashVars.file){
		if(flashVars.file.toLowerCase().indexOf(".mp4") != -1){
			buildServicePlayer(flashVars.file,originalPlugin,flashVars.autostart,"url",flashVars);
		}else if(flashVars.file.toLowerCase().indexOf(".flv") != -1){
			if(supportsFLV){
				buildServicePlayer(flashVars.file,originalPlugin,flashVars.autostart,"url",flashVars);
			}
		}else if(flashVars.file.toLowerCase().indexOf(".mp3") != -1 || flashVars.file.toLowerCase().indexOf(".aac") != -1){
			buildAudioPlayer(flashVars.file,originalPlugin,flashVars.autostart);
		}else{
			buildServicePlayer(flashVars.file,originalPlugin,flashVars.autostart,"JW",flashVars);
		}
		return;
	}
	// Some YouTube videos (and all onsite video players)
	if(flashVars.video_id && flashVars.video_id.length == 11){
		if(flashVars.autoplay == undefined){
			if(flashVars.el == "embedded" || flashVars.el == "videoeditor"){
				flashVars.autoplay = false;
			}else{
				flashVars.autoplay = true;
			}
		}else if(flashVars.autoplay == "true"){
			flashVars.autoplay = true;
		}else if(flashVars.autoplay == "0"){
			flashVars.autoplay = false;
		}else if(flashVars.autoplay == "1"){
			flashVars.autoplay = true
		}else if(flashVars.autoplay == "false"){
			flashVars.autoplay = false;
		}
		if(flashVars.feature == "autoplay"){
			flashVars.autoplay = true;
		}
		buildServicePlayer(flashVars.video_id,originalPlugin,flashVars.autoplay,"YouTube",flashVars,"http://www.youtube.com/watch?v="+flashVars.video_id);
		return;
	}
	// YouTube /v/ embeds
	if(src.indexOf("youtube.com/v/") != -1 || src.indexOf("youtube-nocookie.com/v/") != -1){
		buildServicePlayer(src.between("/v/",false),originalPlugin,flashVars.autoplay,"YouTube",flashVars,
		"http://www.youtube.com/watch?v="+src.between("/v/",false));
		return;
	}
	// GiantRealm (a CDN)
	if(src.indexOf("v.giantrealm.com") != -1){
		var videoId = flashVars.vi;
		var videoURL = "http://play.giantrealm.com/video/"+videoId+"/video.xml";
		buildServicePlayer(videoURL,originalPlugin,false,"url",flashVars);
		return;
	}
	// Flash MP3 Player
	if(flashVars.soundFile){
		buildAudioPlayer(flashVars.soundFile,originalPlugin,flashVars.autostart);
		return;
	}
	// Another Flash MP3 Player
	if(flashVars.url && flashVars.url.indexOf(".mp3") != -1){
		buildAudioPlayer(flashVars.url,originalPlugin,flashVars.autostart);
		return;
	}
	// Megavideo /v/ embeds
	if(src.indexOf("megavideo.com/v/") != -1){
		buildServicePlayer(src.between("megavideo.com/v/","/"), originalPlugin, false, "MegaVideo", flashVars);
		return;
	}
	// MegaVideo encrypted FlashVars
	if(src.indexOf("megavideo.com/mv_player.swf") != -1){
		if(supportsFLV){
			var video = {
				un: flashVars.un,
				k1: flashVars.k1,
				k2: flashVars.k2,
				s:	 flashVars.s,
				v:	 flashVars.v
			};
			var url = getVideoFromMegavideo(video);
			buildServicePlayer(url,originalPlugin,false,"url",flashVars);
		}
		return;
	}
	// DailyMotion
	if(flashVars.sequence){
		if(url = getVideoFromDMSequence(flashVars.sequence)){
			buildServicePlayer(url, originalPlugin, false, "url", flashVars);
			return;
		}
	}
	// IGN
	if(src == "http://media.ign.com/ev/embed.swf" && supportsFLV){
		if(!flashVars.config){
			var ntwk = 12;
			if(window.location.href.indexOf("gamespy")){
				ntwk = 22;
			}else if(window.location.href.indexOf("rottentomatoes")){
				ntwk = 26;
			}
			var str = flashVars.vgroup+"|"+flashVars.object+"|"+ntwk;
		}else{
			str = flashVars.config
		}
		buildServicePlayer(str,originalPlugin,false,"IGN",flashVars);
	}
	// Funny or Die
	if(src.toLowerCase() == "http://player.ordienetworks.com/flash/fodplayer.swf" && supportsFLV){
		buildServicePlayer("http://videos0.ordienetworks.com/videos/"+flashVars.key+"/sd.flv",originalPlugin,false,"url");
		return;
	}
	// Vimeo
	if(src.contains("moogaloop") && src.contains("vimeo")){
	//	buildServicePlayer(flashVars.clip_id,originalPlugin,flashVars.autoplay,"vimeo");
		return;
	}
	// CollegeHumor
	if(src.contains("moogaloop") && src.contains("collegehumor")){
		buildServicePlayer(flashVars.clip_id,originalPlugin,flashVars.autoplay,"collegehumor");
		return;
	}
	// Google Video Player
	if(src.indexOf("googleplayer.swf") != -1){
		buildServicePlayer(flashVars.videoUrl,originalPlugin,flashVars.autoplay,"url",flashVars);
		return;
	}
	// Veoh
	if(src.indexOf("veoh.com/static/swf/webplayer") != -1){
		if(supportsFLV){
			buildServicePlayer(flashVars.parmalinkId,originalPlugin,flashVars.autoPlay,"veoh");
		}
		return;
	}
	//if(src.indexOf("viddler.com/player/") != -1){
	//  Blowfish Sekrit Key: "kluczyk"
	//  POST URL: http://www.viddler.com/amfgateway.action
	//  Content-type: application/x-amf
	// 
	//	buildServicePlayer()
	//}
	// JibJab (both of these)
	if(flashVars.templateXML){
		if(supportsFLV){
			buildServicePlayer(flashVars.templateXML,originalPlugin,flashVars.autoplay,"JibJab");
		}
		return;
	}
	if(flashVars.templateID){
		if(supportsFLV){
			buildServicePlayer(flashVars.templateID,originalPlugin,flashVars.autoplay,"JibJab");
		}
		return;
	}
	// CNN
	if(src.contains("cnn_video.swf")){
		if(supportsFLV){
			var size = flashVars.context.between(false,"_");
			var sizex = size.between(false,"x");
			var sizey = size.between("x",false);
			sizey = Number(sizey)-24;
			size = sizex+"x"+sizey;
			var flvURL = "http://ht.cdn.turner.com/cnn/big/"+flashVars.contentId+"_"+size+"_dl.flv";
			flashVars.thumbnailUrl = "http://www.cnn.com/video/"+flashVars.contentId+"."+size+".jpg";
			buildServicePlayer(flvURL,originalPlugin,flashVars.autoplay,"url",flashVars);
		}
		return;
	}
}
function trim(stringToTrim) {
	return stringToTrim.replace(/^\s+|\s+$/g,"");
}
function ltrim(stringToTrim) {
	return stringToTrim.replace(/^\s+/,"");
}
function rtrim(stringToTrim) {
	return stringToTrim.replace(/\s+$/,"");
}
function xmlEncode(input)
{	
	if(input == undefined)	
	{
		console.log("error in xml_encode: input undefined");	
		return;
	}
	input	=	trim(input.toString());
	
	var replace_with	=	'&amp;';
	// The 'g' in the first argument is used to tell the function 'replace' 
	// that all occurences (g = global)
	// of the character in between slashes have to be replaced.
	input 				= 	input.replace(/&/g,	replace_with);
	
	replace_with		=	'&lt;';
	input 				= 	input.replace(/</g,	replace_with);
	
	replace_with		=	'&gt;';
	input 				= 	input.replace(/>/g,	replace_with);
	
	replace_with		=	'&apos;';
	input 				= 	input.replace(/'/g,	replace_with);
		
	replace_with		=	'&quot;';
	input 				= 	input.replace(/"/g,	replace_with);
	
	return input;
}
pandora_serialize_item = function (item, output)
{
	output.push("<value>");
	var __reg5 = typeof item;
	var __local2 = __reg5;
	if (__local2 == "object") 
	{
		__local2;
		if (item.constructor == Array) 
		{
			output.push("<array><data>");
			var __reg4 = 0;
			while (__reg4 < item.length) 
			{
				pandora_serialize_item(item[__reg4], output);
				++__reg4;
			}
			output.push("</data></array>");
		}
		else 
		{
			output.push("<struct>");
			for (var __reg3 in item) 
			{
				if (item[__reg3] != null) 
				{
					output.push("<member>");
					output.push("<name>");
					output.push(__reg3);
					output.push("</name>");
					pandora_serialize_item(item[__reg3], output);
					output.push("</member>");
				}
			}
			output.push("</struct>");
		}
	}
	else 
	{
		if (__local2 == "number") 
		{
			__local2;
			output.push("<int>");
			output.push(item);
			output.push("</int>");
		}
		else 
		{
			if (__local2 == "boolean") 
			{
				__local2;
				output.push("<boolean>");
				output.push(item ? "1" : "0");
				output.push("</boolean>");
			}
			else 
			{
				if (__local2 == "string") 
				{
					__local2;
					output.push("<string>");
					output.push(xmlEncode(item));
					output.push("</string>");
				}
				else 
				{
					__local2;
					console.log("unknown type: " + __reg5 + ", value: " + item + ", current output: " + output.join(""));
				}
			}
		}
	}
	output.push("</value>");
};
pandora_serialize_request = function (method, params)
{
	//if (XmlRpcMethod.mustSyncMethod(method)) 
	//{
	//	params = [XmlRpcMethod.SYNC_SERVER + (Util.getEpochSeconds() - XmlRpcMethod.SYNC_CLIENT)].concat(params);
	//}
	var __reg3 = [];
	__reg3.push("<?xml version=\"1.0\"?><methodCall><methodName>");
	__reg3.push(method);
	__reg3.push("</methodName><params>");
	var __reg4 = 0;
	while (__reg4 < params.length) 
	{
		__reg3.push("<param>");
		pandora_serialize_item(params[__reg4], __reg3);
		__reg3.push("</param>");
		++__reg4;
	}
	__reg3.push("</params></methodCall>");
	return __reg3.join("");
};
safari.self.tab.dispatchMessage("loadHTML5Video", "");

var iframes = document.getElementsByTagName("iframe");
for(var i = 0; i < iframes.length; i++){
	var element = iframes[i];
	if(element.src.toLowerCase().indexOf("youtube.com/embed/") != -1){
	   element.outerHTML = element.outerHTML.replace(/iframe/gi,"embed").replace("/embed/","/v/");
	}
}